package main

import (
	"fmt"
	"reflect"
)

type Book struct {
	id     int
	title  string
	author string
}

func printBook(book Book) {
	fmt.Println("book id: ", book.id, "id is 0: ", book.id == 0)
	fmt.Println("book title: ", book.title, "title is '': ", book.title == "")
	fmt.Println("book author: ", book.author, "author is '': ", book.author == "")
	fmt.Println()
}

func testStruct() {
	book1 := Book{1, "Go从入门到放弃", "unknown"}
	printBook(book1)

	book2 := Book{id: 2, title: "Python从入门到放弃"}
	printBook(book2)

	book3 := Book{title: "Java从入门到放弃", author: "leo"}
	printBook(book3)
}

func printStructPointer(book *Book) {
	fmt.Println("[func|printStructPointer]type of book=", reflect.TypeOf(book))
	fmt.Println("book.id=", book.id, "type=", reflect.TypeOf(book.id))
	fmt.Println("book.title=", book.title, "type=", reflect.TypeOf(book.title))
	fmt.Println("book.author=", book.author, "type=", reflect.TypeOf(book.author))
	fmt.Println()
}

func testStructPointer() {
	book := Book{4, "JavaScript从入门到放弃", "unknown"}
	fmt.Println("[func|testStructPointer]type of book=", reflect.TypeOf(book))
	structPtr := &book
	fmt.Println("[func|testStructPointer]type of structPtr=", reflect.TypeOf(structPtr))
	printStructPointer(structPtr)

	var structPtr1 *Book
	structPtr1 = &book
	fmt.Println("[func|testStructPointer]type of structPtr1=", reflect.TypeOf(structPtr1))
	printStructPointer(structPtr1)
}

func (book Book) printBook() {
	fmt.Println("[method|printBook]book id: ", book.id, "id is 0: ", book.id == 0)
	fmt.Println("[method|printBook]book title: ", book.title, "title is '': ", book.title == "")
	fmt.Println("[method|printBook]book author: ", book.author, "author is '': ", book.author == "")
	fmt.Println()
}

// 不会改变外部Book的值
func (book Book) changeBookTitle1() {
	book.title = "CSS从入门到放弃"
	book.printBook()
	fmt.Println()
}

// 会改变外部Book的值
func (book *Book) changeBookTitle2() {
	book.title = "Ruby从入门到放弃"
	book.printBook()
	fmt.Println()
}

func testMethod() {
	book := Book{5, "Html从入门到放弃", "unknown"}
	book.printBook()

	fmt.Println("[func|testMethod|changeBookTitle1]")
	book.changeBookTitle1()
	printBook(book)

	fmt.Println("[func|testMethod|changeBookTitle2]")
	book.changeBookTitle2()
	printBook(book)
}

func main() {
	testStruct()
	testStructPointer()
	testMethod()
}
